import json
from decimal import Decimal

from django.db import transaction
from django.http import JsonResponse
from django.utils import timezone
from django.views import View
# Create your views here.
from carts.utils import CartHelper
from goods.models import SKU
from meiduo_mall.utils.mixins import LoginRequiredMixin

# GET /orders/settlement/
from orders.models import OrderInfo, OrderGoods
from users.models import Address


class OrderSettlementView(LoginRequiredMixin, View):
    @staticmethod
    def get(request):
        # 获取当前用户的收货地址信息
        addresses = Address.objects.filter(user=request.user, is_delete=False)
        try:
            cart_helper = CartHelper(request)
            cart_dict = cart_helper.get_redis_selected_cart()
        except Exception:
            return JsonResponse({'code': 400,
                                 'message': '获取购物车数据失败'})

        sku_li = []
        try:
            skus = SKU.objects.filter(id__in=cart_dict.keys())

            for sku in skus:
                sku_li.append({
                    'id': sku.id,
                    'name': sku.name,
                    'default_image_url': ''.join(['http://192.168.19.131:8888/', sku.default_image.name]),
                    'price': sku.price,
                    'count': cart_dict[sku.id]
                })
        except Exception:
            return JsonResponse({'code': 400,
                                 'message': '获取商品数据失败'})
        # 订单运费
        freight = Decimal(10.00)

        # 地址信息
        address_li = []

        try:
            for address in addresses:
                address_li.append({
                    'id': address.id,
                    'province': address.province.name,
                    'city': address.city.name,
                    'district': address.district.name,
                    'place': address.place,
                    'receiver': address.receiver,
                    'mobile': address.mobile
                })
        except Exception:
            return JsonResponse({'code': 400,
                                 'message': '地址信息获取有误'})

        context = {
            'addresses': address_li,
            'skus': sku_li,
            'freight': freight,
            'nowsite': request.user.default_address_id
        }
        return JsonResponse({'code': 0,
                             'message': 'OK',
                             'context': context})


# POST /orders/commit/
class OrderCommitView(LoginRequiredMixin, View):
    @staticmethod
    def post(request):
        req_data = json.loads(request.body)
        address_id = req_data.get('address_id')
        pay_method = req_data.get('pay_method')

        user = request.user

        if not all([address_id, pay_method]):
            return JsonResponse({'code': 400,
                                 'message': '缺少必传参数'})

        try:
            address = Address.objects.get(id=address_id, user=user)
        except Exception:
            return JsonResponse({'code': 400,
                                 'message': '地址信息有误'})

        if pay_method not in [1, 2]:
            return JsonResponse({'code': 400,
                                 'message': '支付方式有误'})

        order_id = timezone.now().strftime('%Y%m%d%H%M%S') + f'{user.id:09}'

        total_count = 0
        total_amount = 0

        if pay_method == 1:
            status = 2
        else:
            status = 1

        freight = Decimal(10.00)

        with transaction.atomic():
            sid = transaction.savepoint()
            order = OrderInfo.objects.create(order_id=order_id,
                                             user=user,
                                             address=address,
                                             total_count=total_count,
                                             total_amount=total_amount,
                                             freight=freight,
                                             pay_method=pay_method,
                                             status=status)

            cart_helper = CartHelper(request)
            cart_dict = cart_helper.get_redis_selected_cart()
            sku_ids = cart_dict.keys()

            for sku_id in sku_ids:
                for i in range(3):
                    sku = SKU.objects.get(id=sku_id)
                    count = cart_dict[sku_id]

                    origin_stock = sku.stock
                    origin_sales = sku.sales

                    # 打印下单提示信息
                    print('下单用户：%s 商品库存：%d 购买数量：%d 尝试第 %d 次' % (
                        user.username, sku.stock, count, i + 1))

                    if count > sku.stock:
                        transaction.savepoint_rollback(sid)
                        return JsonResponse({'code': 400,
                                             'message': '商品库存不足'})

                    # 更新商品库存和销量
                    new_stock = origin_stock - count
                    news_sales = origin_sales + count

                    res = SKU.objects.filter(id=sku.id, stock=origin_stock).update(stock=new_stock, sales=news_sales)

                    if res == 0:
                        if i == 2:
                            # 尝试下单更新了 3 次，仍然失败，报下单失败错误
                            # 数据库操作时，撤销事务中指定保存点之后的操作
                            transaction.savepoint_rollback(sid)
                            return JsonResponse({'code': 400,
                                                 'message': '下单失败!'})
                        continue

                    # sku.stock -= count
                    # sku.sales += count
                    # sku.save()

                    sku.spu.sales += count
                    sku.spu.save()

                    OrderGoods.objects.create(order=order,
                                              sku=sku,
                                              count=count,
                                              price=sku.price)

                    total_count += count
                    total_amount += count * sku.price

                    break

            total_amount += freight
            order.total_count = total_count
            order.total_amount = total_amount
            order.save()

        cart_helper.clear_redis_selected_cart()

        return JsonResponse({'code': 0,
                             'message': '下单成功',
                             'order_id': order_id})


